﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;


/** 
 ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **
 * Description: 
 * Author: Heller (HellerSong@outlook.com)
 * CreationTime: 4/5/2015 10:54:05 AM
 ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 
 **/
namespace DevLib.FileTool
{
	public class XmlEditor
	{
		/* Rule: 
		 *		A one-time operation for static method;
		 *		A frequence operation for instance method with specified XML file;
		 */
		private enum SearchingMode { InnerText, Attribute }
		private String xmlFile;
		private XmlDocument doc;
		private XmlElement root;

		public XmlEditor(String xmlFile)
		{
			this.xmlFile = xmlFile;
			doc = new XmlDocument();
			doc.Load(xmlFile);
			root = doc.DocumentElement;

		}
		public XmlEditor(String xmlFile, String rootName)
		{
			this.xmlFile = xmlFile;
			doc = new XmlDocument();
			doc.Load(xmlFile);
			root = doc.DocumentElement[rootName];
		}


		private static Boolean IsSearched(XmlNode node, String searchingText, SearchingMode mode)
		{
			if (mode.Equals(SearchingMode.InnerText))
			{
				if (node.InnerText.Equals(searchingText, StringComparison.OrdinalIgnoreCase))
					return true;
			}
			else if (mode.Equals(SearchingMode.Attribute))
			{
				// Detect attribute value contains target text
				foreach (XmlAttribute a in node.Attributes)
					if (a.Value.Equals(searchingText, StringComparison.CurrentCultureIgnoreCase))
						return true;
			}

			return false;
		}
		private static XmlNode FindFirstInTree(XmlNode root, String searchingText, SearchingMode mode)
		{
			XmlNode searchResult = null;

			if (root.NodeType.Equals(XmlNodeType.Element))
			{
				if (IsSearched(root, searchingText, mode))
					return searchResult = root;
				else
				{
					XmlNodeList nodeList = root.ChildNodes;
					for (int i = 0; i < nodeList.Count; i++)
					{
						searchResult = FindFirstInTree(nodeList.Item(i), searchingText, mode);
						if (searchResult != null)
							break;
					}
				}
			}

			return searchResult;
		}

		public static XmlElement GetElementByInnerText(String xmlFile, String searchingText)
		{
			XmlElement element = null;
			XmlDocument doc = new XmlDocument();
			doc.Load(xmlFile);
			XmlElement root = doc.DocumentElement;

			element = (XmlElement)FindFirstInTree(root, searchingText, SearchingMode.InnerText);

			return element;
		}
		//public static XmlElement getElementByInnerText(XmlNode root, String searchingText)
		//{
		//    return (XmlElement)findFirstInTree(root, searchingText, SearchingMode.InnerText);
		//}
		public static XmlElement GetElementByAttributeContainText(String xmlFile, String searchingText)
		{
			XmlElement element = null;
			XmlDocument doc = new XmlDocument();
			doc.Load(xmlFile);
			XmlElement root = doc.DocumentElement;

			element = (XmlElement)FindFirstInTree(root, searchingText, SearchingMode.Attribute);

			return element;
		}
		public static Boolean IsElementContainAttribure(XmlElement element, String attribureValue)
		{
			Boolean result = false;

			for (int i = 0; i < element.Attributes.Count; i++)
				if (attribureValue.Equals(element.Attributes[i].Value, StringComparison.OrdinalIgnoreCase))
				{
					result = true;
					break;
				}

			return result;
		}


		public void RemoveNode(XmlNode node)
		{
			node.ParentNode.RemoveChild(node);
		}
		public void SaveXml()
		{
			doc.Save(xmlFile);
		}

	}
}
